package priv.dajie.tzzq.bot.steam;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import priv.dajie.tzzq.bot.base.BaseBot;
import priv.dajie.tzzq.bot.buff.exception.BuffLoginException;
import priv.dajie.tzzq.bot.exception.NetworkException;
import priv.dajie.tzzq.bot.model.RasKeyResponse;
import priv.dajie.tzzq.bot.steam.exception.SteamCantGetLoginKeyException;
import priv.dajie.tzzq.bot.steam.exception.SteamLoginException;
import priv.dajie.tzzq.bot.steam.exception.SteamLoginExceptionCode;
import priv.dajie.tzzq.common.Tools;
import priv.dajie.tzzq.verifyRec.VerifyRec;

import java.io.InputStream;
import java.math.BigInteger;
import java.security.*;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SteamUser extends BaseBot {
    private String steamID;
    // 验证码ID
    private String captchaID;

    private Pattern captchPattern = Pattern.compile("gidCaptcha: \"(.*)\"");
    private Pattern steamidPattern = Pattern.compile("[0-9]{17}");

    public SteamUser(String userName, String passWord) {
        this(userName, passWord, userName + "steam.cookies");
    }

    public SteamUser(String userName, String passWord, String cookiesName) {
        super(userName, passWord, cookiesName);
        captchaID = "-1";
    }

    public void login() throws SteamLoginException, NetworkException, BuffLoginException{
        login(null, null, null);
    }

    public String getSteamId() {
        return steamID;
    }

    public String getCaptchNum(){
        HttpGet httpGet = new HttpGet("https://steamcommunity.com/login/home/");
        String html = open(httpGet, true);
        Matcher matcher = captchPattern.matcher(html);
        if(matcher.find()) {
            captchaID =  matcher.group(1);
        }
        System.out.println(captchaID);
        httpGet = new HttpGet("https://steamcommunity.com/login/rendercaptcha/?gid="+captchaID);
        HttpResponse response = openPro(httpGet, true);
        try {
            InputStream inputStream = response.getEntity().getContent();
            byte[] bytes = Tools.readInputStream(inputStream);
            inputStream.close();
            return VerifyRec.capreg(bytes,"30600").getCode();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void login(String twofactorcode, String emailauth, String code) throws SteamLoginException, NetworkException, BuffLoginException {

        if (loadCookie() && isLogin()) {
            return;
        }
        RasKeyResponse rasKeyResponse = getRsaKey();
        HttpPost httpPost = new HttpPost("https://steamcommunity.com/login/dologin/");
        //设置请求参数
        List<NameValuePair> data = new ArrayList<>();
        data.add(new BasicNameValuePair("donotcache", String.valueOf(System.currentTimeMillis())));
        data.add(new BasicNameValuePair("password", getEncryptedPassword(rasKeyResponse)));
        data.add(new BasicNameValuePair("username", userName));
        data.add(new BasicNameValuePair("twofactorcode", twofactorcode));
        data.add(new BasicNameValuePair("emailauth", emailauth));
        data.add(new BasicNameValuePair("loginfriendlyname", ""));
        data.add(new BasicNameValuePair("captchagid", captchaID));
        data.add(new BasicNameValuePair("captcha_text", code));
        data.add(new BasicNameValuePair("emailsteamid", ""));
        data.add(new BasicNameValuePair("rsatimestamp", rasKeyResponse.getRsatimestamp()));
        data.add(new BasicNameValuePair("remember_login", "true"));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(data));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new SteamLoginException(e.getMessage());
        }

        String response = open(httpPost, true);
        JSONObject json = JSONObject.parseObject(response);
        //判断登陆状态
        if (json.getBoolean("requires_twofactor") != null && json.getBoolean("requires_twofactor")) {
            throw new SteamLoginException("需要两步验证", SteamLoginExceptionCode.TWO);
        }
        if (json.getBoolean("emailauth_needed") != null && json.getBoolean("emailauth_needed")) {
            throw new SteamLoginException("需要邮箱验证", SteamLoginExceptionCode.EMAIL);
        }
        if (!json.getBoolean("success")) {
            throw new SteamLoginException("登陆失败" + json, SteamLoginExceptionCode.OTHER);
        } else {
            if (json.getBoolean("success")) {
                JSONObject transferParameters = json.getJSONObject("transfer_parameters");
                steamID = transferParameters.getString("steamid");
                if (isLogin()) {
                    saveCookies();
                }
            }
//            System.out.println(json);
        }
    }

    public boolean isLogin() throws NetworkException {
        HttpGet httpGet = new HttpGet("https://steamcommunity.com/");
        String text = open(httpGet, true);
        Document document = Jsoup.parse(text);
        Element accountDiv = document.getElementById("account_pulldown");
        // 获取steamID
        if (accountDiv != null) {
            Element a = document.select("a.popup_menu_item").first();
            String href = a.attr("href");

            Matcher matcher = steamidPattern.matcher(href);
            if (matcher.find()) {
                steamID = matcher.group(0);
            }
//            System.out.println(steamID);
        }
        // 判断用户名DIV是否存在
        return accountDiv != null;
    }

    private RasKeyResponse getRsaKey() throws SteamCantGetLoginKeyException, NetworkException {
        HttpPost httpPost = new HttpPost("https://steamcommunity.com/login/getrsakey/");
        List<NameValuePair> data = new ArrayList<>();
        data.add(new BasicNameValuePair("username", userName));
        data.add(new BasicNameValuePair("donotcache", String.valueOf(System.currentTimeMillis())));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(data));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new SteamCantGetLoginKeyException(e.getMessage());
        }
        JSONObject json;
        RasKeyResponse rasKeyResponse;
        int i = 0;
        String webText;
        while (true) {
            webText = open(httpPost, true);
            json = JSONObject.parseObject(webText);
            if (json.getBoolean("success")) {
                rasKeyResponse = new RasKeyResponse(json.getString("publickey_exp"), json.getString("publickey_mod"), json.getString("timestamp"));
                break;
            } else {
                if (i >= 3) {
                    throw new SteamCantGetLoginKeyException("无法获取key");
                }
                i++;
            }
        }
        return rasKeyResponse;
    }

    public String getSessionID() {
        return getCookiesByName("sessionid");
    }

    private String getEncryptedPassword(RasKeyResponse rasKeyResponse) {
        BigInteger mod = new BigInteger(rasKeyResponse.getPublicKeyMod(), 16);
        BigInteger exp = new BigInteger(rasKeyResponse.getPublicKeyExp(), 16);
        RSAPublicKeySpec spec = new RSAPublicKeySpec(mod, exp);
        byte[] encodedPassword = null;
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey key = keyFactory.generatePublic(spec);
            Cipher rsa = Cipher.getInstance("RSA");
            rsa.init(Cipher.ENCRYPT_MODE, key);
            encodedPassword = rsa.doFinal(password.getBytes("ASCII"));
        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | UnsupportedEncodingException | BadPaddingException | InvalidKeySpecException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        if (encodedPassword != null) {
            return DatatypeConverter.printBase64Binary(encodedPassword);
        }
        return null;
    }
    public String getHeaderCookiesStr(){
        List<Cookie> cookies = getAllCookies();
        StringBuilder cookiesStr = new StringBuilder();
        for(Cookie cookie: cookies) {
            cookiesStr.append(cookie.getName()).append("=").append(cookie.getValue()).append(";");
        }
        return cookiesStr.toString();
    }

    @Override
    public Header getHeaderCookies(){
        return new BasicHeader("Cookie", getHeaderCookiesStr());
    }

    public static void main(String[] args) throws SteamLoginException, IOException {
        SteamUser steamUser = new SteamUser("764240419", "6988324haijie24");
        steamUser.login("6C75P", null, null);
        System.out.println(steamUser.isLogin());
    }

}

